import { Callout, Sandpack } from '@/components'

# queryOptions

<Callout type='warning'>

**@suspensive/react-query에서 Deprecated**

이 인터페이스는 이제 TanStack Query v4.40.0+에서 공식적으로 지원됩니다. TanStack Query에서 백포팅했으므로, @suspensive/react-query의 백포팅된 버전을 deprecated 처리합니다. 공식 TanStack Query 인터페이스로 마이그레이션하세요:

```diff
- import { queryOptions } from '@suspensive/react-query'
+ import { queryOptions } from '@tanstack/react-query'
```

자세한 내용은 [TanStack Query PR #9140](https://github.com/TanStack/query/pull/9140)을 참고하세요.

</Callout>

TanStack Query의 메인테이너 [Tkdodo의 TanStack Query v5의 queryOptions 설명 영상](https://youtu.be/bhE3wuB_TuA?feature=shared&t=1697)에서 이 interface가 필요한 이유를 잘 설명되어 있습니다.
TanStack Query v4에서도 queryOptions를 활용할 수 있습니다.

1. queryKey와 queryFn을 묶어서 처리해 queryKey관리가 쉬워집니다.
2. 불필요한 커스텀 쿼리 훅을 제거할 수 있습니다. TanStack Query v4의 `useQuery`, `useQueries`, Suspensive React Query의 `useSuspenseQuery`, `useSuspenseQueries`, `SuspenseQuery`에 모두 직접 사용할 수 있기 때문입니다.
3. TanStack Query v5에는 이미 queryOptions가 제공되고 있기 때문에 TanStack Query v4에서 TanStack Query v5로의 마이그레이션이 쉬워집니다.

```jsx /queryOptions/
import { queryOptions, useSuspenseQuery, useSuspenseQueries, SuspenseQuery } from '@suspensive/react-query'
import { useQuery, useQueries, useQueryClient } from '@tanstack/react-query'

const postQueryOptions = (postId) =>
  queryOptions({
    queryKey: ['posts', postId] as const,
    queryFn: ({
      queryKey: [, postId], // queryKey를 활용할 수 있습니다.
    }) => fetch(`https://example.com/posts/${postId}`),
  })

// 커스텀 쿼리 훅을 만들 필요가 없습니다.
// useQuery, useQueries, useSuspenseQuery, useSuspenseQueries, SuspenseQuery에서 직접 queryOptions를 활용할 수 있습니다.
const post1Query = useQuery(postQueryOptions(1))
const { data: post1 } = useSuspenseQuery({
  ...postQueryOptions(1),
  refetchInterval: 2000, // 사용처에서 확장성을 명확히 표현됩니다.
})
const [post1Query, post2Query] = useQueries({
  queries: [postQueryOptions(1), { ...postQueryOptions(2), refetchInterval: 2000 }],
})
const [{ data: post1 }, { data: post2 }] = useSuspenseQueries({
  queries: [postQueryOptions(1), { ...postQueryOptions(2), refetchInterval: 2000 }],
})
const Example = () => <SuspenseQuery {...postQueryOptions(1)}>{({ data: post1 }) => <>{post1.text}</>}</SuspenseQuery>

// queryClient의 메소드에서 queryKey와 queryFn을 쉽게 활용할 수 있습니다.
const queryClient = useQueryClient()
queryClient.refetchQueries(postQueryOptions(1))
queryClient.prefetchQuery(postQueryOptions(1))
queryClient.invalidateQueries(postQueryOptions(1))
queryClient.fetchQuery(postQueryOptions(1))
queryClient.resetQueries(postQueryOptions(1))
queryClient.cancelQueries(postQueryOptions(1))

```

<Sandpack>

```tsx Example.tsx active
import { Suspense } from '@suspensive/react'
import { queryOptions, SuspenseQuery } from '@suspensive/react-query'
import { useQueryClient } from '@tanstack/react-query'
import { getPost } from './api'

const postQueryOptions = (postId: number) =>
  queryOptions({
    queryKey: ['posts', postId],
    queryFn: () => getPost(postId),
  })

export const Example = () => {
  const queryClient = useQueryClient()

  return (
    <div>
      <button onClick={() => queryClient.resetQueries(postQueryOptions(1))}>
        Reset Query
      </button>
      <Suspense fallback={<div>Loading...</div>}>
        <SuspenseQuery {...postQueryOptions(1)}>
          {({ data }) => {
            return (
              <div>
                <h1>{data.title}</h1>
                <p>{data.body}</p>
              </div>
            )
          }}
        </SuspenseQuery>
      </Suspense>
    </div>
  )
}
```

```tsx api.ts
type Post = {
  userId: number
  id: number
  title: string
  body: string
}

export const getPost = async (id: number): Promise<Post> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts/${id}`
  )

  if (!response.ok) {
    throw new Error('An error occurred')
  }

  const data = await response.json()

  return data
}
```

</Sandpack>

### 버전 기록

| Version  | Changes                                                                                                                 |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `v3.0.0` | `networkMode`는 제거되었습니다. 자세한 내용은 [v3로 마이그레이션하기 문서](./migration/migrate-to-v3.mdx)를 참고하세요. |
